#include "gui.h"
#include "main.h"
#include <sstream>
#include <QtGui>

//#define DEPLOY_APP // uncomment of you want to deploy graph cut as a .app for people who do not have qt

using namespace errlog;
int					ArgParser::findPosition (int argc, char *argv[], std::string f) {
	std::ostringstream s;
	for (int i = 1; i<argc; ++i) {
		s.str("");
		s<<argv[i];
		if (s.str()==f)
			return i;
	}
	return 0;
}
std::string	ArgParser::parseFile(int argc, char *argv[], std::string f) {
	int i = findPosition(argc, argv, f);
	std::ostringstream s;
	if (i>0 && i<argc-1) {
		s<<argv[i+1];
		return s.str();
	}
	return "";
}
bool				ArgParser::parseFlag(int argc, char *argv[], std::string f) {
	int i = findPosition(argc, argv, f);
	if (i>0 && i<argc)
		return true;
	else
		return false;
}
bool				ArgParser::parseSquare(int argc, char *argv[], std::string f, int &o, int &l, int &u, int &r) {
	int i = findPosition(argc, argv, f);
	if (i>0 && i<argc-4) {
		o = atoi(argv[i+1]);
		l = atoi(argv[i+2]);
		u = atoi(argv[i+3]);
		r = atoi(argv[i+4]);
		return true;
	}
	return false;
}
void usage(char *argv[]) {
	std::cout	<< " Usage: " << argv[0] << " [-i infile -o outfile [--sqare upper left lower right | --trimap trimapfile]]" << std::endl
						<< " When no option is given, GUI will start."<<std::endl<<std::endl
						<< "  Options:"<<std::endl
						<< " -i infile                   Image that should be loaded"<<std::endl
						<< " -o outfile                  File that the segmentend image should be stored to"<<std::endl
						<< " --square up le lo ri        Four int values that will define the location of the marking sqare"<<std::endl
						<< " --trimap trimapfile         Trimapfile that will be loaded (will override --square)"<<std::endl
						<< " --quiet                     Program will shut up"<<std::endl
						<< " --verbose                   Program wil be talky (overrides --quiet)"<<std::endl;
}
int main(int argc, char *argv[]) {
#ifndef Q_OS_MAC
    if (argc<=1) {
#endif
		QApplication app(argc, argv);
#if defined Q_OS_MAC && defined DEPLOY_APP
		QApplication::setLibraryPaths(QStringList(qApp->applicationDirPath() + "/../Plugins"));	
#endif
	
#ifdef DEBUG
		/* use log if in debug mode*/
		ErrorCtr::getInstance()->addLogger(new FileLogger("graphcut.log"));
//		ErrorCtr::getInstance()->addLogger(new PrintLogger());
		ErrorCtr::getInstance()->setLogLevel(errlog::verbose);
#else
		/* else use dialog*/
		ErrorCtr::getInstance()->addLogger(new DialogLogger());
		ErrorCtr::getInstance()->setLogLevel(errlog::warning);
#endif
		//use application mode
		MainWindow window;
		window.show();
		return app.exec();
#ifndef Q_OS_MAC	
	} else {
		QCoreApplication app(argc, argv);
		ErrorCtr::getInstance()->addLogger(new PrintLogger());
		ErrorCtr::getInstance()->setLogLevel(errlog::warning);
		//parse argv
		std::string		in =	ArgParser::parseFile(argc,argv,"-i"),
									out =	ArgParser::parseFile(argc,argv,"-o"),
									tri = ArgParser::parseFile(argc,argv,"--trimap");
		int						o,l,u,r;
		o=l=u=r=-1;
		std::ostringstream s;
		if (ArgParser::parseFlag(argc,argv,"--help")) {
			usage(argv);
			exit(1);
		}
		if (ArgParser::parseFlag(argc,argv,"--verbose")) {
			ErrorCtr::getInstance()->setLogLevel(errlog::verbose);
		} else if (ArgParser::parseFlag(argc,argv,"--quiet")) {
			ErrorCtr::getInstance()->setLogLevel(errlog::critical);
		}
		if (in=="") {		CRITICAL("No infile given.");		exit(2); }
		if (out=="") {	CRITICAL("No outfile given.");	exit(2); }
		if (tri=="" && !ArgParser::parseSquare(argc,argv,"--square",o,l,u,r)) { CRITICAL("Neither --square nor --trimap completely given"); exit(3);}
		//now everything is known
		QString qsFileName(in.c_str());
		QImage qoIn(qsFileName);
		s.str("");
		s<<"Image is size of "<<qoIn.width()<<":"<<qoIn.size().height();
		VERBOSE(s.str());
		if (qoIn.isNull()) { CRITICAL ("Unable to load image \""+qsFileName.toStdString() + "\"");	exit(4); }
		Trimap t;
		t.resize(qoIn.width(),qoIn.height());
		//Load trimap
		if (tri != "") {
			if (!t.fromFile(tri)) {	CRITICAL ("Trimap file is invalid"); exit(5);}
		} else if (!t.markSquare(o,l,u,r)) { CRITICAL("Sqare marks invalid"); exit(6);}
		Model *m = new GmdModel();
		m->setImage(Image(qoIn));
		m->train(t);
		if (tri=="")
			t.resize(t.getWidth(), t.getHeight());
		GraphCut g(Image(qoIn), t, m);
		Multimap seg = g.process();
		QRgb tmp;
		int w = qoIn.size().width(),
				h = qoIn.size().height();
		qoIn = qoIn.convertToFormat(QImage::Format_ARGB32);
		for (int x = 0; x<w; ++x)
		for (int y = 0; y<h; ++y) {
			tmp = qoIn.pixel(x,y);
			qoIn.setPixel(x,y,qRgba(qRed(tmp),qGreen(tmp),qBlue(tmp),seg.getXY(x,y)));
		}
		qoIn.save(QString(out.c_str()));
	}
#endif
}
